import * as lodash from 'lodash';
import * as Koa from 'koa';
import {
  addPicture,
  updatePicture,
  searchPicture,
  searchPictureTotalNumbers
} from '../entity/picture';
import { copyFile, dealWithKey, deleteFile, joinDefaultFields, valideDirname } from '../utils/index';
import { OssService } from './oss';
import getConnection from '../mysql/connection';
const dayjs = require('dayjs');
const sharp = require('sharp');
const path = require('path');
// TODO：commonjs 模式下引用 esmodule 模块
let nanoid: any = null;
(async () => {
  nanoid = (await eval("import('nanoid')")).nanoid;
})();

const errorMsg = `服务器错误：${'user'}`;
const successMsg = `成功：${'user'}`;

export default class PictureService {
  /**
   * 修改
   * @param ctx
   */
  updatePicture = async (ctx: Koa.Context) => {
    try {
      let picture = ctx.request.body;
      picture.update_time = dayjs().format("YYYY-MM-DD HH:mm:ss"); // 最后的更新时间
      picture = dealWithKey(picture);
      const result: any = picture && (await updatePicture(ctx, picture));
      if (!result) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else if (!result.success) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else {
        ctx.success(null, '成功');
      }
    } catch (error) {
      ctx.fail(null, errorMsg, -1);
    }
  };

  /**
   * 查询；注意搜索用的模糊搜索
   * @param ctx
   */
  searchPicture = async (ctx: Koa.Context) => {
    try {
      const params = ctx.request.body;
      const {
        include_url, // 图片所属用户
        exclude_url, // 排除图片所属用户的其它图片
        pid,
        title,
        picTags,
        captureTime,
        description,
        isExcellent,
        isMainPic,
        belongAuth,
        searchVal,
        orders,
        pageNumber,
        pageSize,
      } = params || {}; // 查询条件
      if (!include_url && !exclude_url) return ctx.fail(null, 'include_url、exclude_url不能同时为空', -1);
      if (!pageNumber || !pageSize) return ctx.fail(null, 'currentPage、pageSize不能为空', -1);
      // 相等、模糊条件
      let condition = "";
      let equals: string | string[] = [];
      pid && (equals.push(` pid = "${pid}"`));
      captureTime && (equals.push(` capture_time = "${captureTime}"`));
      isExcellent && (equals.push(` is_excellent = "${isExcellent}"`));
      isMainPic && (equals.push(` is_main_pic = "${isMainPic}"`));
      // 默认一定加上
      equals.push(` is_origin = "0"`); // 批量查询一定是非原图
      equals.push(` is_show = "1"`);

      (title || searchVal) && (equals.push(` title LIKE "%${title || searchVal}%"`));
      description && (equals.push(` description LIKE "%${description}%"`));
      exclude_url && (equals.push(` url NOT LIKE "%${exclude_url}%"`));
      include_url && (equals.push(` url LIKE "%${include_url}%"`));
      equals = equals.join(" AND");
      equals && (condition += `WHERE ${equals}`);
      // 排序的条件
      orders?.column && orders.order && (condition += ` ORDER BY ${orders.column} ${orders.order}`);
      // 查总数的条件不需要分页参数
      const conditionTotal = condition;
      // 分页的条件
      condition += ` LIMIT ${pageSize} OFFSET ${(pageNumber - 1) * pageSize}`;
      const result: any = await searchPicture(ctx, { condition });
      const resultNums: any = await searchPictureTotalNumbers(ctx, { condition: conditionTotal });
      if (!result) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else if (!result.success) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else {
        ctx.success({
          list: result.data || [],
          total: resultNums?.data || 0,
          pageNumber: pageNumber,
          pageSize: pageSize,
        }, successMsg);
      }
    } catch (error) {
      ctx.fail(null, error, -1);
    }
  };

  /**
   * 添加为主图
   * @param ctx
   */
  moveInMainPic = async (ctx: Koa.Context) => {
    try {
      const { pid } = ctx.request.body;
      if (!pid || !pid.length) return ctx.fail(null, "pid不能为空", -1);
      const pids = Array.isArray(pid)? pid : [pid];
      if (!pids?.length) return ctx.fail(null, '请传入指定图片ID', -1);
      const picture = {
        is_main_pic: "1",
        update_time: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 最后的更新时间
      };
      const errorItems = [];
      for (const _id of pids) {
        const result: any = picture && (await updatePicture(ctx, Object.assign(picture, { pid: _id })));
        if (!result?.success) {
          errorItems.push(_id);
        }
      }
      if (!!errorItems.length) {
        ctx.fail(null, errorMsg, -1);
      } else {
        ctx.success(null, '成功');
      }
    } catch (error) {
      ctx.fail(null, errorMsg, -1);
    }
  };

  /**
   * 移除目录
   * @param ctx
   */
  moveOut = async (ctx: Koa.Context) => {
    try {
      const { pid } = ctx.request.body;
      if (!pid || !pid.length) return ctx.fail(null, "pid不能为空", -1);
      const pids = Array.isArray(pid)? pid : [pid];
      const picture = {
        is_show: "0",
        is_excellent: "0",
        is_main_pic: "0",
        update_time: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 最后的更新时间
      };
      const errorItems = [];
      for (const _id of pids) {
        const result: any = picture && (await updatePicture(ctx, Object.assign(picture, { pid: _id })));
        if (!result?.success) {
          errorItems.push(_id);
        }
      }
      if (!!errorItems.length) {
        ctx.fail(null, errorMsg, -1);
      } else {
        ctx.success(null, '成功');
      }
    } catch (error) {
      ctx.fail(null, errorMsg, -1);
    }
  };

  /**
   * 移除精选
   * @param ctx
   */
  moveOutExcellent = async (ctx: Koa.Context) => {
    try {
      const { pid } = ctx.request.body;
      if (!pid || !pid.length) return ctx.fail(null, "pid不能为空", -1);
      const pids = Array.isArray(pid)? pid : [pid];
      if (!pids?.length) return ctx.fail(null, '请传入指定图片ID', -1);
      const picture = {
        is_excellent: "0",
        update_time: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 最后的更新时间
      };
      const errorItems = [];
      for (const _id of pids) {
        const result: any = picture && (await updatePicture(ctx, Object.assign(picture, { pid: _id })));
        if (!result?.success) {
          errorItems.push(_id);
        }
      }
      if (!!errorItems.length) {
        ctx.fail(null, errorMsg, -1);
      } else {
        ctx.success(null, '成功');
      }
    } catch (error) {
      ctx.fail(null, errorMsg, -1);
    }
  };

  /**
   * 移出主图
   * @param ctx
   */
  moveOutMainPic = async (ctx: Koa.Context) => {
    try {
      const { pid } = ctx.request.body;
      if (!pid || !pid.length) return ctx.fail(null, "pid不能为空", -1);
      const pids = Array.isArray(pid)? pid : [pid];
      if (!pids?.length) return ctx.fail(null, '请传入指定图片ID', -1);
      const picture = {
        is_main_pic: "0",
        update_time: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 最后的更新时间
      };
      const errorItems = [];
      for (const _id of pids) {
        const result: any = picture && (await updatePicture(ctx, Object.assign(picture, { pid: _id })));
        if (!result?.success) {
          errorItems.push(_id);
        }
      }
      if (!!errorItems.length) {
        ctx.fail(null, errorMsg, -1);
      } else {
        ctx.success(null, '成功');
      }
    } catch (error) {
      ctx.fail(null, errorMsg, -1);
    }
  };

  /**
   * 移入精选
   * @param ctx
   */
  moveInExcellent = async (ctx: Koa.Context) => {
    try {
      const { pid } = ctx.request.body;
      if (!pid || !pid.length) return ctx.fail(null, "pid不能为空", -1);
      const pids = Array.isArray(pid)? pid : [pid];
      if (!pids?.length) return ctx.fail(null, '请传入指定图片ID', -1);
      const picture = {
        is_excellent: "1",
        update_time: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 最后的更新时间
      };
      const errorItems = [];
      for (const _id of pids) {
        const result: any = picture && (await updatePicture(ctx, Object.assign(picture, { pid: _id })));
        if (!result?.success) {
          errorItems.push(_id);
        }
      }
      if (!!errorItems.length) {
        ctx.fail(null, errorMsg, -1);
      } else {
        ctx.success(null, '成功');
      }
    } catch (error) {
      ctx.fail(null, errorMsg, -1);
    }
  };

  /**
   * 前端图片上传
   * @param ctx
   */
  pictureUpload = async (ctx: Koa.Context) => {
    let originFilePath = "";
    let copyFilePath = "";
    try {
      const params = ctx.request.body;
      const file = ctx.request.files.file; // 上传的文件
      const { pathOne, pathTwo, captureTime } = params || {}; // 上传路径，拍摄时间
      if (!pathOne) return ctx.fail(null, '用户前缀路径不能为空', -1);

      originFilePath = file.filepath;
      await valideDirname(`${path.dirname(originFilePath)}\\zip`); // 校验文件夹
      copyFilePath = `${path.dirname(originFilePath)}\\zip\\${path.basename(originFilePath)}`; // 压缩文件输出路径
      await copyFile(originFilePath, copyFilePath); // 复制压缩文件
      const originOutputPath = `${pathOne}/large${pathTwo ? '/' + pathTwo : ''}`;
      const copyOutputPath = `${pathOne}/small${pathTwo ? '/' + pathTwo : ''}`;

      // 上传原图
      let ossService = new OssService(originFilePath, originOutputPath, {
        name: file.originalFilename,
        captureTime: captureTime,
        isOrigin: "1",
      });
      let res = await ossService.send(ctx);
      if (!res.result) {
        ctx.fail(res, res.msg || "上传失败", -1);
        return;
      }
      ossService = null;
      res = null;
      // 上传压缩图
      ossService = new OssService(copyFilePath, copyOutputPath, {
        name: file.originalFilename,
        captureTime: captureTime,
        isOrigin: "0",
      });
      res = await ossService.send(ctx);
      if (!res.result) {
        ctx.fail(res, res.msg || "上传失败", -1);
        return;
      }
      ctx.success(res, res.msg || "上传成功");
    } catch (error) {
      ctx.fail(null, error, -1);
    } finally {
      await deleteFile(originFilePath);
      await deleteFile(copyFilePath);
    }
  };

  // 数据同步到MySQL - 代码层面使用
  uploadDataToMysql = async (ctx: Koa.Context) => {
    const tableName = "picture";
    let connection: any = null;
    try {
      const jsonDataArray: any = ctx.request.body;
      const db = ctx.dbPool;
      connection = await getConnection(db);
      // 获取列名
      const keys = Object.keys(jsonDataArray[0]);
      const columns = keys.join(', ');

      // 构造值列表字符串，每个数据对象对应一组问号
      const placeholdersPerRow = "(" + keys.map(() => '?').join(', ') + ")";
      const allPlaceholders = Array(jsonDataArray.length).fill(placeholdersPerRow).join(', ');

      // 构建完整的SQL插入语句
      const sql = `INSERT INTO ${tableName} (${columns}) VALUES ${allPlaceholders}`;

      // 将所有数据对象的值展平为一个数组
      const values = jsonDataArray.flatMap(Object.values);

      // 执行预处理语句
      const [result] = await connection.execute(sql, values);
      ctx.success({}, "成功");
    } catch (error) {
      ctx.fail(null, error, -1);
    } finally {
      if (connection) connection.release();
    }
  };

  /**
   * 添加
   * @param ctx
   */
  addPicture = async (ctx: Koa.Context) => {
    try {
      const picture = ctx.request.body;
      const _picture = joinDefaultFields(picture, "pictureFields");
      _picture.pid = nanoid(18);
      _picture.create_time = dayjs().format("YYYY-MM-DD HH:mm:ss");
      const result: any = _picture && await addPicture(ctx, _picture);
      if (!result) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else if (!result.success) {
        ctx.fail(null, result.msg ||errorMsg, -1);
      } else {
        ctx.success(null, successMsg);
      }
    } catch (error) {
      ctx.fail(null, errorMsg, -1);
    }
  };

  /**
   * 删除 - 只做标识删除
   * @param ctx
   */
  delelePicture = async (ctx: Koa.Context) => {
    this.moveOut(ctx);
  };

  /**
   * 小程序中查询被审核通过的图片，用于在主页中显示的公共图片
   * @param ctx
   */
  appletSearchPicture = async (ctx: Koa.Context) => {
    try {
      const { pageNumber, pageSize, orders, searchVal } = ctx.request.body;
      // 相等、模糊条件
      let condition = "";
      let equals: string | string[] = [];
      equals.push(` is_show = "1" AND is_origin = "0" AND is_approved = "1"`);
      searchVal && (equals.push(` title LIKE "%${searchVal}%"`));
      equals = equals.join(" AND");
      equals && (condition += `WHERE ${equals}`);
      // 排序的条件
      orders?.column && orders.order && (condition += ` ORDER BY ${orders.column} ${orders.order}`);
      // 查总数的条件不需要分页参数
      const conditionTotal = condition;
      // 分页的条件
      if (pageSize && pageNumber) {
        condition += ` LIMIT ${pageSize} OFFSET ${(pageNumber - 1) * pageSize}`;
      }
      const result = await searchPicture(ctx, { condition });
      const resultNums: any = await searchPictureTotalNumbers(ctx, { condition: conditionTotal });
      if (!result?.success) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else {
        ctx.success({
          list: result.data || [],
          total: resultNums?.data || 0,
          pageNumber: pageNumber,
          pageSize: pageSize
        }, successMsg);
      }
    } catch (error) {
      ctx.fail(null, error, -1);
    }
  };
  appletGetMainPicture = async (ctx: Koa.Context) => {
    try {
      // 相等、模糊条件
      let condition = "";
      let equals: string | string[] = [];
      equals.push(` is_show = "1" AND is_origin = "0" AND is_approved = "1" AND is_main_pic = "1"`);
      equals && (condition += `WHERE ${equals}`);
      const result = await searchPicture(ctx, { condition });
      if (!result?.success) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else {
        ctx.success(result.data || [], successMsg);
      }
    } catch (error) {
      ctx.fail(null, error, -1);
    }
  };


  /**
   * 查询；注意搜索用的模糊搜索 - 指定用户权限的所有图片
   * @param ctx
   */
  appletSearchPersonPicture = async (ctx: Koa.Context) => {
    try {
      const { include_url, pageNumber, pageSize } = ctx.request.body;
      if (!include_url) return ctx.fail(null, "参数错误，include_url不能为空", -1);
      // 相等、模糊条件
      let condition = "";
      let equals: string | string[] = [];
      equals.push(` is_show = "1" AND is_origin = "0"`);
      include_url && (equals.push(` url LIKE "%${include_url}%"`));
      equals = equals.join(" AND");
      equals && (condition += `WHERE ${equals}`);
      // 查总数的条件不需要分页参数
      const conditionTotal = condition;
      // 分页的条件
      if (pageSize && pageNumber) {
        condition += ` LIMIT ${pageSize} OFFSET ${(pageNumber - 1) * pageSize}`;
      }
      const result = await searchPicture(ctx, { condition });
      const resultNums: any = await searchPictureTotalNumbers(ctx, { condition: conditionTotal });
      if (!result?.success) {
        ctx.fail(null, result.msg || errorMsg, -1);
      } else {
        ctx.success({
          list: result.data || [],
          total: resultNums?.data || 0,
          pageNumber: pageNumber,
          pageSize: pageSize
        }, successMsg);
      }
    } catch (error) {
      ctx.fail(null, error, -1);
    }
  };

  /**
   * 获取图片，不是分页的 ？？？ 直接把pageSize设置成最大值就好了，或是加个是否分页的参数
   * @param ctx
   */
  getPicture = async (ctx: Koa.Context) => {};
}
